﻿/*------------------------------------------------------------------------

VECTOR.HPP v1.1.6

Copyright 楊志賢 CxxlMan, 2012 - 2014
All Rights Reserved

------------------------------------------------------------------------*/


#if !defined(__VECTOR_HPP_Cxxl3D)
#define __VECTOR_HPP_Cxxl3D

#include <xmmintrin.h>
#include <CRITICAL.HPP>
#include <CXXL3DCOMMON.HPP>
#include <mem\C3DMEM.HPP>


namespace Cxxl3D
{

class Vector4;
class Matrix4x4;


// 三維向量 * 值
inline Vector4 cxxlFASTCALL operator*(const Vector4 &v, const C3D_FLOAT Value);

// 值 * 三維向量
inline Vector4 cxxlFASTCALL operator*(const C3D_FLOAT Value, const Vector4 &v);

// 三維向量 + 三維向量
inline Vector4 cxxlFASTCALL operator+(const Vector4 &lhs, const Vector4 &rhs);

// 三維向量 - 三維向量
inline Vector4 cxxlFASTCALL operator-(const Vector4 &lhs, const Vector4 &rhs);

// 三維向量 - 三維向量
inline Vector4 cxxlFASTCALL operator-(const Vector4 &rhs);


// 三維向量 / 值
inline Vector4 cxxlFASTCALL operator/(const Vector4 &v, const C3D_FLOAT Value);

// 求出三維內積
inline C3D_FLOAT cxxlFASTCALL Vector3Dot(const Vector4 &a, const Vector4 &b);

// 求出三維外積
inline Vector4 cxxlFASTCALL Vector3CrossProduct(const Vector4 &a, const Vector4 &b);

// 取得向量長度
inline C3D_FLOAT cxxlFASTCALL Vector3Length(const Vector4 &a);


// 三維正規化
inline void cxxlFASTCALL Vector3Normalize(Vector4 &a);


// 產生繞指定向量旋轉的矩陣
inline Matrix4x4 cxxlFASTCALL Rotate(const Vector4 &v, const C3D_FLOAT fSin, const C3D_FLOAT fCos);


// 座標轉換矩陣的反矩陣函數
inline Matrix4x4 cxxlFASTCALL CoordinateInvert(const Matrix4x4 &m);


struct C3DVector4
{
  union
  {
 	  __m128 m_Vec;
	  struct 
	  {
      C3D_FLOAT x,y,z,w;
	  };
	  C3D_FLOAT m_elem[4];
  };

  // Constructor
  C3DVector4(C3D_FLOAT xarg,C3D_FLOAT yarg,C3D_FLOAT zarg,C3D_FLOAT warg=0.0)
  {
    x = xarg;
    y = yarg;
    z = zarg;
    w = warg;
  }

  // Constructor
  C3DVector4()
  {
  }

 	C3D_FLOAT & cxxlFASTCALL operator[](int index)
  {
    return m_elem[index];
  }

 	C3D_FLOAT cxxlFASTCALL operator[](int index) const
  {
    return m_elem[index];
  }

};

// 未做同步控制，所以不適合共享
class Vector4:private C3DVector4
{
  // CxxlMan::CriticalSec csObject;

public:

  // Constructor
  Vector4()
  {
  }


  // Constructor
  Vector4(C3D_FLOAT xarg, C3D_FLOAT yarg, C3D_FLOAT zarg, C3D_FLOAT warg = 0.0)
  {
    x = xarg;
    y = yarg;
    z = zarg;
    w = warg;
  }

  // Constructor
  Vector4(const C3DVector4 &C3DVector4_Arg)
  {
    *(C3DVector4 *)this = C3DVector4_Arg;
  }

  // Copy Constructor
  Vector4(const Vector4 &Vector4_Arg)
  {
    //Vector4_Arg.csObject.Enter();
    *(C3DVector4 *)this = *(C3DVector4 *)&Vector4_Arg;
    //Vector4_Arg.csObject.Leave();
  }

  // Copy
  Vector4 & cxxlFASTCALL operator=(const Vector4 &Vector4_Arg)
  {
/*
    Vector4 tmp(Vector4_Arg); // 在 Copy Constructor 有同步控制

    csObject.Enter();
    *(C3DVector4*)this = *(C3DVector4 *)&tmp;
    csObject.Leave();
*/   
    *(C3DVector4 *)this = *(C3DVector4 *)&Vector4_Arg;
    return *this;
  }

  // 複製 C3DVector4
  C3DVector4 cxxlFASTCALL Get_C3DVector4() const
  {
  //  CxxlMan::CriticalSecHandle AutoCSH(csObject);

    return *(C3DVector4 *)this;
  }

  // 轉形
  // 適用於 const
  cxxlFASTCALL operator const C3DVector4&() const
  {
    return *(const C3DVector4 *)this;
  }

  // 轉形
  cxxlFASTCALL operator C3DVector4&()
  {
    return *(C3DVector4 *)this;
  }


  inline C3D_FLOAT & cxxlFASTCALL operator[](int Index)
  {
    return m_elem[Index];
  }

  inline const C3D_FLOAT cxxlFASTCALL operator[](int Index) const
  {
    return m_elem[Index];
  }

	inline void cxxlFASTCALL SetX(C3D_FLOAT xarg)
	{
    x = xarg;
	}

	inline void cxxlFASTCALL SetY(C3D_FLOAT yarg)
	{
    y = yarg;
	}

	inline void cxxlFASTCALL SetZ(C3D_FLOAT zarg)
	{
    z = zarg;
	}

	inline void cxxlFASTCALL SetW(C3D_FLOAT warg)
	{
    w = warg;
	}

  inline void cxxlFASTCALL SetXYZ(C3D_FLOAT p)
  {
    //csObject.Enter();
    x = p;
    y = p;
    z = p;
    //csObject.Leave();
  }

	inline const C3D_FLOAT cxxlFASTCALL GetX(void) const
	{
		return x;
	}

	inline const C3D_FLOAT cxxlFASTCALL GetY(void) const
	{
		return y;
	}

	inline const C3D_FLOAT cxxlFASTCALL GetZ(void) const
	{
		return z;
	}

	inline const C3D_FLOAT cxxlFASTCALL GetW(void) const
	{
		return w;
	}


  void * operator new(size_t s)
  {
    return AllocateAlignedMemory(s);
  }

  void operator delete(void *m,size_t s) 
  {
    ReleaseAlignedMemory(m);
  }

  void *operator new [](size_t s)
  {
    return AllocateAlignedMemory(s);
  }

  void operator delete [](void *m,size_t s) 
  {
    ReleaseAlignedMemory(m);
  }


  friend class Matrix4x4;

  // 三維向量 * 值
  friend inline Vector4 cxxlFASTCALL operator*(const Vector4 &v, const C3D_FLOAT Value);

  // 值 * 三維向量
  friend inline Vector4 cxxlFASTCALL operator*(const C3D_FLOAT Value, const Vector4 &v);

  // 三維向量 + 三維向量
  friend inline Vector4 cxxlFASTCALL operator+(const Vector4 &lhs, const Vector4 &rhs);

  // 三維向量 - 三維向量
  friend inline Vector4 cxxlFASTCALL operator-(const Vector4 &lhs, const Vector4 &rhs);

  // 三維向量 - 三維向量
  friend inline Vector4 cxxlFASTCALL operator-(const Vector4 &rhs);

  // 三維向量 / 值
  friend inline Vector4 cxxlFASTCALL operator/(const Vector4 &v, const C3D_FLOAT Value);

  // 求出三維內積
  friend inline C3D_FLOAT cxxlFASTCALL Vector3Dot(const Vector4 &a, const Vector4 &b);

  // 求出三維外積
  friend inline Vector4 cxxlFASTCALL Vector3CrossProduct(const Vector4 &a, const Vector4 &b);


  // 取得向量長度
  friend inline C3D_FLOAT cxxlFASTCALL Vector3Length(const Vector4 &a);

  // 三維正規化
  friend inline void cxxlFASTCALL Vector3Normalize(Vector4 &a);


  // 產生繞指定向量旋轉的矩陣
  friend inline Matrix4x4 cxxlFASTCALL Rotate(const Vector4 &v, const C3D_FLOAT fSin, const C3D_FLOAT fCos);

  // 座標轉換矩陣的反矩陣函數
  friend inline Matrix4x4 cxxlFASTCALL CoordinateInvert(const Matrix4x4 &m);

};


}   /* namespace Cxxl3D */
#endif

